#include "../header.h"

//TODO 服务端编程
//1.socket 建立服务端套接字   - sid建立链接
//2.bind - port - ip - 网卡
//3.listen - 监听。
//4.accept - 链接-的结果  cid - 读写套接字
//5.读写
//6.关闭

//2个字符串进去。
int TCP_Init(const char * port,const char *ip)
{
    //1.
    int sid = socket(AF_INET,SOCK_STREAM,0);
    if(sid < 0 )
    {
        perror("socket error\n");
        return -1;
    }
    printf("套接字建立成功:%d\n",sid);
    //实际地址结构体，
    struct sockaddr_in saddr = {0};
    //ipv4协议族
    saddr.sin_family = AF_INET;
    //ip + port填写。
    saddr.sin_addr.s_addr = inet_addr(ip);
    saddr.sin_port = htons(atoi(port));  
    //port + sid + ip
    //2通用地址结构体
   if(bind(sid,(struct sockaddr*)&saddr,sizeof(saddr)) < 0 )
    {
        perror("bind error\n");
    }
    printf("绑定成功!\n");
    //3
    if(listen(sid,10) < 0 )
    {
        perror("监听失败!\n");
    }
    printf("监听成功!\n");
    //4 链接 - 阻塞  
    //第二个参数是对面的地址结构体。
    struct sockaddr_in caddr = {0};
    int size = sizeof(caddr);
    int cid = accept(sid,(struct sockaddr*)&caddr,&size);
    if(cid < 0 )
    {
        perror("链接失败!\n");
    }
    //本cid用来进行读写。
    printf("链接成功:cid = %d\n",cid);

    //解析客户端数据 - 解析客户端 ip + port
    printf("客户端的端口号:%d\n",ntohs(caddr.sin_port));
    char ipk[16] = {0};
    printf("客户端的ip地址是:%s\n",inet_ntop(AF_INET,&caddr.sin_addr,ipk,sizeof(ipk)));
    //单用户 - 一次读写。
    //读写操作 - 先读再写
    char bufs[128] = "";
    int readlen = 0 ;
    char bufn[128] = "";
    //先读-再写。
    //主要任务 - 键盘-屏幕-文件-客户端cid -sid
    while(strncmp(bufs,"quit",4))
    {
        //清空缓冲区bufs
        bzero(bufs,sizeof(bufs));
        //read阻塞
        readlen = read(cid,bufs,sizeof(bufs));
        printf("客户端发送过来的数据是:%s 数据长度是:%d\n",bufs,readlen);

        //写数据
        bzero(bufn,sizeof(bufn));
        printf("请输入数据:");
        //从键盘接收的数据 - 发送到对面。
        fgets(bufn,sizeof(bufn)-1,stdin);
        write(cid,bufn,strlen(bufn));
    }
    close(cid);
    close(sid);
    return 0;

}

int main(int argc, char const *argv[])
{
    //参数判断
    if(argc < 3)
    {
        perror("usage:./a.out + ip + port\n");
        return -1;
    }
    //端口字符串argv[2],ip字符串arg[1];
    //每个函数的返回值可以判定本函数是否执行成功。
    TCP_Init(argv[2],argv[1]);


    return 0;
}
